package com.swim.session;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.ejb.Stateless;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.jboss.ejb3.annotation.LocalBinding;
import org.jboss.ejb3.annotation.RemoteBinding;
import com.swim.entity.FriendshipRequest;
import com.swim.entity.RegisteredUser;

@Stateless
@RemoteBinding(jndiBinding="FriendshipBeanJNDI")
@LocalBinding(jndiBinding="FriendshipBeanLocalJNDI")
public class FriendshipBean implements FriendshipLocal, FriendshipRemote {

	@PersistenceContext(unitName = "SWIM")
	EntityManager database;
	
	/**
	 * @param from the RegisteredUser who sent the request of friendship
	 * @param to the RegisteredUser who received the request of friendship
	 * @param direct says if a friendship passed from a suggestion or no
	 */
	public void newFriendshipRequest(String from, String to, boolean direct) {
		if(canRequestFriendship(from, to)){
			RegisteredUserLocal r = getRegisteredUserLocal();
			FriendshipRequest req = new FriendshipRequest(r.getUserWithEmail(from), r.getUserWithEmail(to), Util.getNow(), direct);
			database.persist(req);
		} else {
			//TODO: se non poteva richiedere l'amicizia?
		}
	}

	/**
	 * @return the local interface of registered user
	 */
	private RegisteredUserLocal getRegisteredUserLocal() {
		InitialContext jndiContext;
		Object ref = null;
		try {
			jndiContext = new InitialContext();
			ref = jndiContext.lookup("RegisteredUserBeanLocalJNDI");
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return (RegisteredUserLocal) ref;
	}

	/**
	 * @param emailTo the email of a person who received some request of friendship
	 * @return the list of the friendship's request received from the user
	 */
	public List<FriendshipRequest> getReceivedFriendshipRequests(String emailTo) {
		
		try {
			RegisteredUserLocal r = getRegisteredUserLocal();
    		List<FriendshipRequest> resultList = new ArrayList<FriendshipRequest>();
    		Set<FriendshipRequest> set = r.getUserWithEmail(emailTo).getReceivedFriendshipRequests();
    		resultList.addAll(set);
			return resultList;
    	} catch (EntityNotFoundException exc) { 
    		System.err.println("UFF1");
    	} catch (javax.persistence.NoResultException exc) { 
    		System.err.println("UFF2");
    	} catch (NonUniqueResultException exc) {
    		System.err.println("UFF3");
    	}
    	return null;
	}

	/**
	 * @param id the id of the friendship's request
	 * @param accept the request's result
	 */
	public void acceptFriendshipRequest(int id, boolean accept) {
		FriendshipRequest f = getFriendshipRequest(id);
		if(accept) {
			RegisteredUser user = f.getEmailFrom();
			user.getFriends().add(f.getEmailTo());
			if(f.isDirect())
					user.getReceivedNotifications().add(f.getEmailTo());
		}
		database.remove(f);
	}

	/**
	 * @param id the of the friendship's request
	 * @return the request of friendship selected by id
	 */
	public FriendshipRequest getFriendshipRequest(int id) {
		try{
			Query q = database.createQuery("SELECT f FROM FriendshipRequest f WHERE f.id=:id");
			q.setParameter("id", id);
			FriendshipRequest result =  (FriendshipRequest) q.getSingleResult();
			return result;
	   	} catch (EntityNotFoundException exc) { 
			System.err.println("UFF1");
		} catch (javax.persistence.NoResultException exc) { 
			System.err.println("UFF2");
		} catch (NonUniqueResultException exc) {
			System.err.println("UFF3");
		}
		return null;
	}

	/**
	 * @param email the email of an user
	 * @param email1 the email of the user
	 * @return a boolean that say if the user can send a friendship's request
	 */
	public boolean canRequestFriendship(String email, String email1) {
		if(email == null || email1 == null || email.equals(email1))
			return false;

		RegisteredUserLocal r = getRegisteredUserLocal();
		RegisteredUser user = r.getUserWithEmail(email);
		RegisteredUser user1 = r.getUserWithEmail(email1);
		if(user1.getFriends().contains(user) || user.getFriends().contains(user1))
			return false;
		
		for (FriendshipRequest f : user.getSentFriendshipRequests()) {
			if(f.getEmailFrom().equals(user) && f.getEmailTo().equals(user1)
					|| f.getEmailFrom().equals(user1) && f.getEmailTo().equals(user))
				return false;
		}

		for (FriendshipRequest f : user.getReceivedFriendshipRequests()) {
			if(f.getEmailFrom().equals(user) && f.getEmailTo().equals(user1)
					|| f.getEmailFrom().equals(user1) && f.getEmailTo().equals(user))
				return false;
		}
		
		return true;
	}

	/**
	 * @param emailTo the email of a person who received some request of friendship
	 * @return the list of the friendship's request received from the user
	 */
	public List<RegisteredUser> getFriendshipRequestsUsers(String emailTo) {
		List<RegisteredUser> resultList = new  ArrayList<RegisteredUser>();
				try{
					Query q = database.createQuery("SELECT f.emailTo FROM FriendshipRequest f WHERE f.emailFrom.email=:email");
					q.setParameter("email", emailTo);
					List<RegisteredUser> result =  (List<RegisteredUser>) q.getResultList();
					resultList.addAll(result);
					q = database.createQuery("SELECT f.emailFrom FROM FriendshipRequest f WHERE f.emailTo.email=:email");
					q.setParameter("email", emailTo);
					result =  (List<RegisteredUser>) q.getResultList();
					resultList.addAll(result);
			   	} catch (EntityNotFoundException exc) { 
					System.err.println("UFF1");
				} catch (javax.persistence.NoResultException exc) { 
					System.err.println("UFF2");
				} catch (NonUniqueResultException exc) {
					System.err.println("UFF3");
				}
		return resultList;
	}
}
